package store

import (
	"encoding/json"
	"errors"

	"github.com/project-flogo/core/data/coerce"

	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
)

type EdgeChannelData struct {
	ID        string       `json:"id,omitempty"`
	Timestamp int64        `json:"timestamp,omitempty"`
	Value     gjson.Result `json:"value,omitempty"`
}

type edgeChannelData struct {
	ID        string          `json:"id,omitempty"`
	Timestamp int64           `json:"timestamp,omitempty"`
	Value     json.RawMessage `json:"value,omitempty"`
}

func (m EdgeChannelData) Serialize() string {
	s := "{}"
	s, _ = sjson.Set(s, "id", m.ID)
	s, _ = sjson.Set(s, "timestamp", m.Timestamp)
	s, _ = sjson.SetRaw(s, "value", m.Value.Raw)
	return s
}

func (m EdgeChannelData) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"id":        m.ID,
		"timestamp": m.Timestamp,
		"value":     m.Value.Raw,
	}
}

func EdgeChannelDataFromMap(m map[string]interface{}) (EdgeChannelData, error) {
	id, err := coerce.ToString(m["id"])
	if err != nil {
		return EdgeChannelData{}, err
	}
	timestamp, err := coerce.ToInt64(m["timestamp"])
	if err != nil {
		return EdgeChannelData{}, err
	}
	str, err := coerce.ToString(m["value"])
	if err != nil {
		return EdgeChannelData{}, err
	}
	if !gjson.Valid(str) {
		return EdgeChannelData{}, errors.New("invald value")
	}
	d := EdgeChannelData{
		ID:        id,
		Timestamp: timestamp,
		Value:     gjson.Parse(str),
	}
	return d, nil
}

func ParseEdgeChannelData(str string) (EdgeChannelData, error) {
	var m edgeChannelData
	err := json.Unmarshal([]byte(str), &m)
	if err != nil {
		return EdgeChannelData{}, err
	}
	md := EdgeChannelData{
		ID:        m.ID,
		Timestamp: m.Timestamp,
		Value:     gjson.ParseBytes(m.Value),
	}
	return md, nil
}
